home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / HTML / Template / PHPLIB.php < prev    next >
PHP Script  |  2004-03-24  |  15KB  |  562 lines

  1. <?php
  2. // vim: set expandtab tabstop=4 shiftwidth=4:
  3. // This code that was derived from the original PHPLIB Template class
  4. // is copyright by Kristian Koehntopp, NetUSE AG and was released
  5. // under the LGPL.
  6. //
  7. // Authors: Kristian Koehntopp <kris@koehntopp.de> (original from PHPLIB)
  8. //          Bjoern Schotte <bjoern@rent-a-phpwizard.de> (PEARification)                
  9. //          Martin Jansen <mj@php.net> (PEAR conformance)            
  10. //
  11. // $Id: PHPLIB.php,v 1.14 2003/06/11 06:03:32 bjoern Exp $
  12. //
  13.  
  14. require_once "PEAR.php";
  15.  
  16. /**
  17.  * Converted PHPLIB Template class
  18.  *
  19.  * For those who want to use PHPLIB's fine template class,
  20.  * here's a PEAR conforming class with the original PHPLIB
  21.  * template code from phplib-stable CVS. Original author
  22.  * was Kristian Koehntopp <kris@koehntopp.de>
  23.  *
  24.  * @author  Bjoern Schotte <bjoern@rent-a-phpwizard.de>
  25.  * @author  Martin Jansen <mj@php.net> (PEAR conformance)
  26.  * @version 1.0
  27.  */
  28. class Template_PHPLIB
  29. {
  30.     /**
  31.      * If set, echo assignments
  32.      * @var bool
  33.      */
  34.     var $debug     = false;
  35.  
  36.     /**
  37.      * $file[handle] = "filename";
  38.      * @var array
  39.      */
  40.     var $file  = array();
  41.  
  42.     /**
  43.      * fallback paths that should be defined in a child class
  44.      * @var array
  45.      */
  46.     var $file_fallbacks = array();
  47.  
  48.     /**
  49.      * Relative filenames are relative to this pathname
  50.      * @var string
  51.      */
  52.     var $root   = "";
  53.  
  54.     /*
  55.      * $_varKeys[key] = "key"
  56.      * @var array
  57.      */
  58.     var $_varKeys = array();
  59.     
  60.     /**
  61.      * $_varVals[key] = "value";
  62.      * @var array
  63.      */
  64.     var $_varVals = array();
  65.  
  66.     /**
  67.      * "remove"  => remove undefined variables
  68.      * "comment" => replace undefined variables with comments
  69.      * "keep"    => keep undefined variables
  70.      * @var string
  71.      */
  72.     var $unknowns = "remove";
  73.   
  74.     /**
  75.      * "yes" => halt, "report" => report error, continue, "no" => ignore error quietly
  76.      * @var string
  77.      */
  78.     var $haltOnError  = "report";
  79.   
  80.     /**
  81.      * The last error message is retained here
  82.      * @var string
  83.      * @see halt
  84.      */
  85.     var $_lastError     = "";
  86.  
  87.  
  88.     /**
  89.      * Constructor
  90.      *
  91.      * @access public
  92.      * @param  string template root directory
  93.      * @param  string how to handle unknown variables
  94.      * @param  array fallback paths
  95.      */
  96.     function Template_PHPLIB($root = ".", $unknowns = "remove", $fallback="")
  97.     {
  98.         $this->setRoot($root);
  99.         $this->setUnknowns($unknowns);
  100.         if (is_array($fallback)) $this->file_fallbacks = $fallback;
  101.     }
  102.  
  103.     /**
  104.      * Sets the template directory
  105.      *
  106.      * @access public
  107.      * @param  string new template directory
  108.      * @return bool
  109.      */
  110.     function setRoot($root)
  111.     {
  112.         if (!is_dir($root)) {
  113.             $this->halt("setRoot: $root is not a directory.");
  114.             return false;
  115.         }
  116.     
  117.         $this->root = $root;
  118.     
  119.         return true;
  120.     }
  121.  
  122.     /**
  123.      * What to do with unknown variables
  124.      *
  125.      * three possible values:
  126.      *
  127.      * - "remove" will remove unknown variables
  128.      *   (don't use this if you define CSS in your page)
  129.      * - "comment" will replace undefined variables with comments
  130.      * - "keep" will keep undefined variables as-is
  131.      *
  132.      * @access public
  133.      * @param  string unknowns
  134.      */
  135.     function setUnknowns($unknowns = "keep")
  136.     {
  137.         $this->unknowns = $unknowns;
  138.     }
  139.  
  140.     /**
  141.      * Set appropriate template files
  142.      *
  143.      * With this method you set the template files you want to use.
  144.      * Either you supply an associative array with key/value pairs
  145.      * where the key is the handle for the filname and the value
  146.      * is the filename itself, or you define $handle as the file name
  147.      * handle and $filename as the filename if you want to define only
  148.      * one template.
  149.      *
  150.      * @access public
  151.      * @param  mixed handle for a filename or array with handle/name value pairs
  152.      * @param  string name of template file
  153.      * @return bool
  154.      */
  155.     function setFile($handle, $filename = "")
  156.     {
  157.         if (!is_array($handle)) {
  158.     
  159.             if ($filename == "") {
  160.                 $this->halt("setFile: For handle $handle filename is empty.");
  161.                 return false;
  162.             }
  163.       
  164.             $this->file[$handle] = $this->_filename($filename);
  165.       
  166.         } else {
  167.     
  168.             reset($handle);
  169.             while (list($h, $f) = each($handle)) {
  170.                 $this->file[$h] = $this->_filename($f);
  171.             }
  172.         }
  173.     }
  174.  
  175.     /**
  176.      * Set a block in the appropriate template handle
  177.      *
  178.      * By setting a block like that:
  179.      *
  180.      * <!-- BEGIN blockname -->
  181.      * html code
  182.      * <!-- END blockname -->
  183.      *
  184.      * you can easily do repeating HTML code, i.e. output
  185.      * database data nice formatted into a HTML table where
  186.      * each DB row is placed into a HTML table row which is
  187.      * defined in this block.
  188.      * It extracts the template $handle from $parent and places
  189.      * variable {$name} instead.
  190.      *
  191.      * @access public
  192.      * @param  string parent handle
  193.      * @param  string block name handle
  194.      * @param  string variable substitution name
  195.      */
  196.     function setBlock($parent, $handle, $name = "")
  197.     {
  198.         if (!$this->_loadFile($parent)) {
  199.             $this->halt("setBlock: unable to load $parent.");
  200.             return false;
  201.         }
  202.     
  203.         if ($name == "") {
  204.             $name = $handle;
  205.         }
  206.  
  207.         $str = $this->getVar($parent);
  208.         $reg = "/[ \t]*<!--\s+BEGIN $handle\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END $handle\s+-->\s*?\n?/sm";
  209.         preg_match_all($reg, $str, $m);
  210.         $str = preg_replace($reg, "{" . "$name}", $str);
  211.  
  212.         if (isset($m[1][0])) $this->setVar($handle, $m[1][0]);
  213.         $this->setVar($parent, $str);
  214.     }
  215.  
  216.     /**
  217.      * Set corresponding substitutions for placeholders
  218.      *
  219.      * @access public
  220.      * @param  string name of a variable that is to be defined or an array of variables with value substitution as key/value pairs
  221.      * @param  string value of that variable
  222.      * @param  boolean if true, the value is appended to the variable's existing value
  223.      */
  224.     function setVar($varname, $value = "", $append = false)
  225.     {
  226.         if (!is_array($varname)) {
  227.  
  228.             if (!empty($varname))
  229.                 if ($this->debug) print "scalar: set *$varname* to *$value*<br>\n";
  230.  
  231.             $this->_varKeys[$varname] = $this->_varname($varname);
  232.             ($append) ? $this->_varVals[$varname] .= $value : $this->_varVals[$varname] = $value;
  233.  
  234.         } else {
  235.             reset($varname);
  236.  
  237.             while (list($k, $v) = each($varname)) {
  238.                 if (!empty($k))
  239.                     if ($this->debug) print "array: set *$k* to *$v*<br>\n";
  240.  
  241.                 $this->_varKeys[$k] = $this->_varname($k);
  242.                 ($append) ? $this->_varVals[$k] .= $v : $this->_varVals[$k] = $v;
  243.             }
  244.         }
  245.     }
  246.  
  247.     /**
  248.      * Substitute variables in handle $handle
  249.      *
  250.      * @access public
  251.      * @param  string name of handle
  252.      * @return mixed string substituted content of handle
  253.      */
  254.     function subst($handle)
  255.     {
  256.         if (!$this->_loadFile($handle)) {
  257.             $this->halt("subst: unable to load $handle.");
  258.             return false;
  259.         }
  260.  
  261.         return @str_replace($this->_varKeys, $this->_varVals, $this->getVar($handle));
  262.     }
  263.   
  264.     /**
  265.      * Same as subst but printing the result
  266.      *
  267.      * @access  public
  268.      * @brother subst
  269.      * @param   string handle of template
  270.      * @return  bool always false
  271.      */
  272.     function pSubst($handle)
  273.     {
  274.         print $this->subst($handle);
  275.         return false;
  276.     }
  277.  
  278.     /**
  279.      * Parse handle into target
  280.      *
  281.      * Parses handle $handle into $target, eventually
  282.      * appending handle at $target if $append is defined
  283.      * as TRUE.
  284.      *
  285.      * @access public
  286.      * @param  string target handle to parse into
  287.      * @param  string which handle should be parsed
  288.      * @param  boolean append it to $target or not?
  289.      * @return string parsed handle
  290.      */
  291.     function parse($target, $handle, $append = false)
  292.     {
  293.         if (!is_array($handle)) {
  294.             $str = $this->subst($handle);
  295.  
  296.             ($append) ? $this->setVar($target, $this->getVar($target) . $str) : $this->setVar($target, $str);
  297.         } else {
  298.             reset($handle);
  299.  
  300.             while (list(, $h) = each($handle)) {
  301.                 $str = $this->subst($h);
  302.                 $this->setVar($target, $str);
  303.             }
  304.         }
  305.  
  306.         return $str;
  307.     }
  308.  
  309.     /**
  310.      * Same as parse, but printing it.
  311.      *
  312.      * @access  public
  313.      * @brother parse
  314.      * @param   string target to parse into
  315.      * @param   string handle which should be parsed
  316.      * @param   should $handle be appended to $target?
  317.      * @return  bool
  318.      */
  319.     function pParse($target, $handle, $append = false)
  320.     {
  321.         print $this->finish($this->parse($target, $handle, $append));
  322.         return false;
  323.     }
  324.   
  325.     /**
  326.      * Return all defined variables and their values
  327.      *
  328.      * @access public
  329.      * @return array with all defined variables and their values
  330.      */
  331.     function getVars()
  332.     {
  333.         reset($this->_varKeys);
  334.  
  335.         while (list($k, ) = each($this->_varKeys)) {
  336.             $result[$k] = $this->getVar($k);
  337.         }
  338.  
  339.         return $result;
  340.     }
  341.  
  342.     /**
  343.      * Return one or more specific variable(s) with their values.
  344.      *
  345.      * @access public    
  346.      * @param  mixed array with variable names or one variable name as a string
  347.      * @return mixed array of variable names with their values or value of one specific variable
  348.      */
  349.     function getVar($varname)
  350.     {
  351.         if (!is_array($varname)) {
  352.             if (isset($this->_varVals[$varname])) {
  353.                 return $this->_varVals[$varname];
  354.             } else {
  355.                 return "";
  356.             }
  357.         } else {
  358.             reset($varname);
  359.     
  360.             while (list($k, ) = each($varname)) {
  361.                 $result[$k] = (isset($this->_varVals[$k])) ? $this->_varVals[$k] : "";
  362.             }
  363.  
  364.             return $result;
  365.         }
  366.     }
  367.   
  368.     /**
  369.      * Get undefined values of a handle
  370.      *
  371.      * @access public
  372.      * @param  string handle name
  373.      * @return mixed  false if an error occured or the undefined values
  374.      */
  375.     function getUndefined($handle)
  376.     {
  377.         if (!$this->_loadFile($handle)) {
  378.             $this->halt("getUndefined: unable to load $handle.");
  379.             return false;
  380.         }
  381.     
  382.         preg_match_all("/{([^ \t\r\n}]+)}/", $this->getVar($handle), $m);
  383.         $m = $m[1];
  384.         if (!is_array($m)) {
  385.             return false;
  386.         }
  387.  
  388.         reset($m);
  389.         while (list(, $v) = each($m)) {
  390.             if (!isset($this->_varKeys[$v])) {
  391.                 $result[$v] = $v;
  392.             }
  393.         }
  394.     
  395.         if (isset($result) && count($result)) {
  396.             return $result;
  397.         } else {
  398.             return false;
  399.         }
  400.     }
  401.  
  402.     /**
  403.      * Finish string
  404.      *
  405.      * @access public
  406.      * @param  string string to finish
  407.      * @return finished, i.e. substituted string
  408.      */
  409.     function finish($str)
  410.     {
  411.         switch ($this->unknowns) {
  412.             case "remove":
  413.                 $str = preg_replace('/{[^ \t\r\n}]+}/', "", $str);
  414.                 break;
  415.  
  416.             case "comment":
  417.                 $str = preg_replace('/{([^ \t\r\n}]+)}/', "<!-- Template $handle: Variable \\1 undefined -->", $str);
  418.                 break;
  419.         }
  420.  
  421.         return $str;
  422.     }
  423.  
  424.     /**
  425.      * Print variable to the browser
  426.      *
  427.      * @access public
  428.      * @param  string name of variable to print
  429.      */
  430.     function p($varname)
  431.     {
  432.         print $this->finish($this->getVar($varname));
  433.     }
  434.  
  435.     /**
  436.      * Get finished variable
  437.      *
  438.      * @access public public
  439.      * @param  string variable to get
  440.      * @return string string with finished variable
  441.      */
  442.     function get($varname)
  443.     {
  444.         return $this->finish($this->getVar($varname));
  445.     }
  446.  
  447.     /**
  448.      * Complete filename
  449.      *
  450.      * Complete filename, i.e. testing it for slashes
  451.      *
  452.      * @access private
  453.      * @param  string filename to be completed
  454.      * @return string completed filename
  455.      */
  456.     function _filename($filename)
  457.     {
  458.         if (substr($filename, 0, 1) != "/") {
  459.             $filename = $this->root."/".$filename;
  460.         }
  461.  
  462.         if (file_exists($filename)) return $filename;
  463.         if (is_array($this->file_fallbacks) && count($this->file_fallbacks) > 0) {
  464.             reset($this->file_fallbacks);
  465.             while (list(,$v) = each($this->file_fallbacks)) {
  466.                 if (file_exists($v.basename($filename))) return $v.basename($filename);
  467.             }
  468.             $this->halt(sprintf("filename: file %s does not exist in the fallback paths %s.",$filename,implode(",",$this->file_fallbacks)));
  469.             return false;
  470.         } else {
  471.             $this->halt(sprintf("filename: file %s does not exist.",$filename));
  472.             return false;
  473.         }
  474.  
  475.         return $filename;
  476.     }
  477.  
  478.     /**
  479.      * Protect a replacement variable
  480.      *
  481.      * @access private
  482.      * @param  string name of replacement variable
  483.      * @return string replaced variable
  484.      */
  485.     function _varname($varname)
  486.     {
  487.         return "{".$varname."}";
  488.     }
  489.  
  490.     /**
  491.      * load file defined by handle if it is not loaded yet
  492.      *
  493.      * @access private
  494.      * @param  string handle
  495.      * @return bool   FALSE if error, true if all is ok
  496.      */
  497.     function _loadFile($handle)
  498.     {
  499.         if (isset($this->_varKeys[$handle]) and !empty($this->_varVals[$handle])) {
  500.             return true;
  501.         }
  502.  
  503.         if (!isset($this->file[$handle])) {
  504.             $this->halt("loadfile: $handle is not a valid handle.");
  505.             return false;
  506.         }
  507.  
  508.         $filename = $this->file[$handle];
  509.         if (function_exists("file_get_contents")) {
  510.             $str = file_get_contents($filename);
  511.         } else {
  512.             if (!$fp = @fopen($filename,"r")) {
  513.                 $this->halt("loadfile: couldn't open $filename");
  514.                 return false;
  515.             }
  516.  
  517.             $str = fread($fp,filesize($filename));
  518.             fclose($fp);
  519.         }
  520.  
  521.         if ($str=='') {
  522.             $this->halt("loadfile: While loading $handle, $filename does not exist or is empty.");
  523.             return false;
  524.         }
  525.  
  526.         $this->setVar($handle, $str);
  527.  
  528.         return true;
  529.     }
  530.  
  531.     /**
  532.      * Error function. Halt template system with message to show
  533.      *
  534.      * @access public
  535.      * @param  string message to show
  536.      * @return bool
  537.      */
  538.     function halt($msg)
  539.     {
  540.         $this->_lastError = $msg;
  541.  
  542.         if ($this->haltOnError != "no") {
  543.             return $this->haltMsg($msg);
  544.         }
  545.  
  546.         return false;
  547.     }
  548.   
  549.     /**
  550.      * printf error message to show
  551.      *
  552.      * @access public
  553.      * @param  string message to show
  554.      * @return object PEAR error object
  555.      */
  556.     function haltMsg($msg)
  557.     {
  558.         PEAR::raiseError(sprintf("<b>Template Error:</b> %s<br>\n", $msg));
  559.     }
  560. }
  561. ?>
  562.